package com.nxy.cpfsfe.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.*;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
public class XMLNodeUtil {
	private static final Log loger = LogFactory.getLog(XMLNodeUtil.class);
	private Document doc = null;
	private OutputFormat fmt = OutputFormat.createCompactFormat();
	@SuppressWarnings("unused")
	private OutputFormat oneLine = OutputFormat.createPrettyPrint();
	
	public final static int FROM_ROOT = 0;
	public final static int FROM_BUFF = 1;
	public final static int FROM_FILE = 2;
	public final static int FROM_ENCODE = 3;
	

	public static XMLNodeUtil Create(int fromType, String tmpStr)  {
		try {
			return new XMLNodeUtil(fromType, tmpStr);
		}
		catch (Exception e) {
			e.printStackTrace();
			// loger.error("create XMLNodeUtil error!fromType=[" + fromType + "]" + e);
			// return null;
		}
		return null;
	}
	
	public XMLNodeUtil setNodeContent(String xpath, String value) {
		loger.debug("set:[" + xpath + "]val=[" + value + "]");
		if (value != null) doc.selectSingleNode(xpath).setText(value);
		return this;
	}
	
	public XMLNodeUtil setNodeContentTrim(String xpath, String value) {
		loger.debug("set:[" + xpath + "]val=[" + value + "]");
		if (value != null) doc.selectSingleNode(xpath).setText(value.trim());
		return this;
	}
	
	/**
	 * 返回xpath指定节点的属性集合
	 * @param xpath
	 * @return
	 */
	public List getNodeAttribute(String xpath) {
		List<Element> element = doc.selectNodes(xpath);
		return element;
	}
	
	public String getNodeContent(String xpath) {
		String str = null;
		str = doc.selectSingleNode(xpath).getText();
		loger.debug("get:[" + xpath + "]str=[" + str + "]");
		return str;
	}
	
	public String getNode(String xpath) {
		String str = null;
		Element elementroot = doc.getRootElement();
		elementroot.getPath(elementroot);
		elementroot.getText();
		System.out.println(elementroot.getName());
		loger.debug("get:[" + xpath + "]str=[" + str + "]");
		return str;
	}
	
	public String getNodeContentTrim(String xpath) {
		String str = null;
		str = doc.selectSingleNode(xpath).getText();
		loger.debug("get:[" + xpath + "]str=[" + str + "]");
		return str == null ? "" : str.trim();
	}
	
	public String getNodeContentNotNUll(String xpath) {
		String str = null;
		str = doc.selectSingleNode(xpath) != null ? doc.selectSingleNode(xpath).getText() : "";
		loger.debug("get:[" + xpath + "]str=[" + str + "]");
		return str == null ? "" : str.trim();
	}
	
	public XMLNodeUtil setNodesContent(String xpath, String value) {
		List nodes = doc.selectNodes(xpath);
		Iterator iter = nodes.iterator();
		while (iter.hasNext())
			((Element) iter.next()).setText(value);
		return this;
	}
	public XMLNodeUtil setNodesContent(String xpath, String[] values) {
		List nodes = doc.selectNodes(xpath);
		Iterator iter = nodes.iterator();
		int i=0;
		while (iter.hasNext()){
			((Element) iter.next()).setText(values[i]);
			i++;
		}

		return this;
	}
	
	public String[] getNodesContent(String xpath) {
		int i = 0;
		List nodes = doc.selectNodes(xpath);
		String[] values = new String[nodes.size()];
		Iterator iter = nodes.iterator();
		while (iter.hasNext()) {
			values[i++] = ((Node) iter.next()).getText();
		}
		return values;
	}

	public XMLNodeUtil setNodesContent(String xpath, String nodeName ,String[] values) {
		Element rootElement = doc.getRootElement();
		Element bodyElement  = (Element)rootElement.selectNodes(xpath).get(0);
		if(values!= null && values.length >0){
			for (int i =0; i<values.length;i++){
				Element element =bodyElement.addElement(nodeName);
				element.setText(values[i]);
			}
		}
		return this;
	}

	public XMLNodeUtil replaceNode(String oldXPath, XMLNodeUtil newDoc, String newXPath) {
		Element oldNode = (Element) (doc.selectNodes(oldXPath).get(0));
		Element newNode = (Element) (newDoc.getDocument().selectNodes(newXPath).get(0));
		oldNode.setContent(newNode.content());
		return this;
	}
	
	public XMLNodeUtil exchgNodeContent(String xpathA, String xpathB) {
		String tmp = getNodeContent(xpathA);
		setNodeContent(xpathA, getNodeContent(xpathB));
		setNodeContent(xpathB, tmp);
		return this;
	}
	
	public XMLNodeUtil setFormat(String encoding, boolean pretty) {
		if (pretty) {
			fmt = OutputFormat.createPrettyPrint();
			fmt.setIndent("    ");
			fmt.setNewlines(true);
		}
		fmt.setEncoding(encoding);
		
		return this;
	}
	
	public int checkValid(String nodesXPath, String attrName) {
		List nodes = doc.selectNodes(nodesXPath + "[@" + attrName + "]");
		Iterator iter = nodes.iterator();
		Element e = null;
		String checkAttr = null;
		String checkValue = null;
		int length = 0;
		int checkLength = 0;
		while (iter.hasNext()) {
			e = ((Element) iter.next());
			checkValue = getNodeContent("//" + e.getText());
			checkAttr = e.attributeValue(attrName);
			length = Integer.parseInt(checkAttr.substring(2));
			checkLength = checkValue.length();
			if (checkAttr.charAt(0) == 'O') {
				if (checkLength == 0) continue;
			}
			else if (checkAttr.charAt(0) != 'M') continue;
			if (checkLength > 0) {
				switch (checkAttr.charAt(1)) {
					case '=': // 必需等于length
						if (checkLength == length) continue;
						else break;
					case '-': // 必需小于length
						if (length > checkLength) continue;
						else break;
					case '+': // 必需大于length
						if (checkLength > length) continue;
						else break;
				}
			}
			loger.error(e.getText() + "元素的值=[" + checkValue + "]不合法!");
			return -1;
		}
		return 0;
	}
	
	public void changeAmtVal(String amtNodesXPath) {
		List nodes = doc.selectNodes(amtNodesXPath);
		Iterator iter = nodes.iterator();
		String checkValue = null;
		String xpath = null;
		int tmp = 0;
		while (iter.hasNext()) {
			loger.info("处理金额类型数据...");
			xpath = "//BODY/" + ((Element) iter.next()).getText();
			checkValue = getNodeContent(xpath);
			if ((tmp = checkValue.indexOf('.')) != -1) setNodeContent(xpath, checkValue.substring(0, tmp));
			loger.info("原值:[" + checkValue + "]新值:[" + getNodeContent(xpath) + "]");
		}
	}
	
	/**转储成字符串(UNICODE编码)*/
	public String toString() {
		ByteArrayOutputStream str = new ByteArrayOutputStream();
		try {
			fmt.setEncoding("UTF-8");
			fmt.setTrimText(true);
			fmt.setNewlines(true);
			// fmt.setIndent(true);
			XMLWriter writer = new XMLWriter(str, fmt);
			writer.write(doc);
			writer.close();
		}
		catch (IOException e) {
			return null;
		}
		return str.toString();
	}
	
	public String dumpToBuff() {
		ByteArrayOutputStream str = new ByteArrayOutputStream();
		try {
			fmt.setEncoding("UTF-8");
			fmt.setTrimText(true);
			XMLWriter writer = new XMLWriter(str, fmt);
			writer.write(doc);
			writer.close();
		}
		catch (IOException e) {
			loger.error("XMLNodeUtil dump to buff error!" + e);
			return null;
		}
		return str.toString();
	}
	
	public int dumpToFile(String fname) {
		try {
			XMLWriter writer = new XMLWriter(new FileWriter(fname), fmt);
			writer.write(doc);
			writer.close();
		}
		catch (IOException e) {
			loger.error("XMLNodeUtil dump to " + fname + " error!" + e);
			return -1;
		}
		return 0;
	}
	
	public XMLNodeUtil(int fromType, String tmpStr) throws DocumentException {
		switch (fromType) {
			case FROM_BUFF:
				doc = DocumentHelper.parseText(tmpStr);
				break;
			case FROM_FILE:
				SAXReader reader = new SAXReader();
				reader.setIgnoreComments(true);
				doc = reader.read(new File(tmpStr));
				break;
			case FROM_ROOT:
				doc = DocumentHelper.createDocument();
				doc.addElement(tmpStr);
				break;
			case FROM_ENCODE:
				doc = new DocumentFactory().createDocument(tmpStr);
				break;
		}
	}
	

	
	public Document getDocument() {
		return this.doc;
	}
	
	public static void main(String[] args) throws Exception {
		StringBuffer rule = new StringBuffer();
		rule.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
		rule.append("<UFTP doctype=\"feerule\">");
		rule.append("<attr ChargeMode=\"1\"  MultiRange=\"Y\"/>");
		rule.append("<period start=\"080000\" end=\"155959\" member=\"Y\" crossarea=\"N\" min=\"1.00\" max=\"20.00\">");
		rule.append("<range from=\"0.01\" to=\"50000.00\">0.02</range>");
		rule.append("<range from=\"50000.01\" to=\"100000.00\">0.01</range>");
		rule.append("<range from=\"100000.01\" to=\"999999999999999.00\">0.005</range>");
		rule.append("</period>");
		rule.append("<period start=\"160000\" end=\"235959\" member=\"Y\" crossarea=\"N\" min=\"1.00\" max=\"10.00\">");
		rule.append("<range from=\"0.01\" to=\"50000.00\">0.02</range>");
		rule.append("<range from=\"50000.01\" to=\"100000.00\">0.01</range>");
		rule.append("<range from=\"100000.01\" to=\"999999999999999.00\">0.005</range>");
		rule.append("</period>");
		rule.append("</UFTP>");
		
		// XMLNodeUtil XMLNodeUtil = XMLNodeUtil.Create(XMLNodeUtil.FROM_BUFF, rule.toString());
		// String result= XMLNodeUtil.getNode("/UFTP/period");
		// System.out.println(result);
		StringBuffer rolexml = new StringBuffer();
		Document document = null;
		document = DocumentHelper.parseText(rule.toString());
		Element rootelement = document.getRootElement(); // 获取根节点
		System.out.println("根节点：" + rootelement.getName()); // 拿到根节点的名称
		List<Element> period = rootelement.elements("period");
		for (int x = 0; x < period.size(); x++) {
			String start = period.get(x).attribute("start").getText();
			String end = period.get(x).attribute("end").getText();
			String member = period.get(x).attribute("member").getText();
			String crossarea = period.get(x).attribute("crossarea").getText();
			String min = period.get(x).attribute("min").getText();
			String max = period.get(x).attribute("max").getText();
			List<Element> range = period.get(x).elements("range");
			for (int y = 0; y < range.size(); y++) {
				String minAmt = range.get(y).attribute("from").getText();
				String maxAmt = range.get(y).attribute("to").getText();
				String fee = range.get(y).getText();
				if (period.size() > 1) {
					rolexml.append("start:" + start + ",");
					rolexml.append("stop:" + end + ",");
					rolexml.append("member:" + member + ",");
					rolexml.append("crossarea:" + crossarea + ",");
					rolexml.append("min:" + min + ",");
					rolexml.append("max:" + max + ",");
					rolexml.append(x + "" + y + ":" + minAmt + "#" + maxAmt + "#" + fee);
					
				}
				else {

				}
				if (y > 1) {
					rolexml.append("T");
				}
			}
		}
		System.out.println("rulexml : " + rolexml.toString());
		// Element element = (Element)doc.getDocument().selectNodes("/tpps/menu").get(0);
		// System.out.println("ss=="+element.asXML());
		// doc = XMLNodeUtil.Create(XMLNodeUtil.FROM_BUFF, element.asXML());
		// doc.setFormat("gbk", false);
		// System.out.println(doc.dumpToBuff());
		/*
		doc.setNodesContent("//QM", "queue");
		String[] tmp = doc.getNodesContent("//QM");
		for (int i = 0; i < tmp.length; i++)
		System.out.println(tmp[i]);
		doc.setNodeContent("//QUEUE[@DESC='RealRecvFromPH']/../@NAME", "test");
		System.out.println(doc.getNodeContent("//QUEUE[@DESC='RealRecvFromPH']/Qname"));
		doc.replaceNode("//HEAD", doc2, "//HEAD");
		
		doc.checkValid("//MapList/*", "STDFMT");
		doc.changeAmtVal("//MapList/*[@TYPE='AMT']");
		*/
		// cispub.setCISConfigInfo();
		// doc.exchgNodeContent("//TrustDate", "//BeneBank");
		
		// System.out.println(doc.dumpToBuff());
		
	}
}
